﻿using Microsoft.AspNetCore.Http;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.Tokens;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using QBZ.Evaluation.Domains.Permissions;
using QBZ.Evaluation.Models;
using QBZ.Evaluation.Repositories;
using QBZ.Evaluation.Repositories.DataAccess;
using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;

namespace QBZ.Evaluation.Domains
{
    public class UserDomain
    {
        private readonly UserRepository _user;
        private readonly IMemoryCache _cache;
        private readonly JwtSettings _jwtSettings;


        public UserDomain(IMemoryCache cache, IOptions<JwtSettings> _jwtSettingsAccesser, UserRepository user)
        {

            _user = user;
            _cache = cache;
            _jwtSettings = _jwtSettingsAccesser.Value;
        }

        public int AddUser(UserModel user)
        {
            return _user.AddUser(user);
        }

        public async Task<string> sendSMSAsync(string phone,int verifyCode)
        {
            
            var sms = new ServiceReferenceSMS.LinkWSSoapClient(new ServiceReferenceSMS.LinkWSSoapClient.EndpointConfiguration());
            return await sms.BatchSend2Async("JNJS006042", "zm0513@", phone, "您的验证码是" + verifyCode.ToString() + ",请在30分钟内完成验证。如非本人操作，请忽略本短信。【云速网络】", "", "");
        }

        public async Task<string> sendRegSMSAsync(string phone)
        {
            Random rd = new Random();
            int verifyCode = rd.Next(100000, 999999);
            return await sendSMSAsync(phone, verifyCode);
        }

        public UserModel FindUser(string userName, string password)
        {
            if (new Regex("^\\s*([A-Za-z0-9_-]+(\\.\\w+)*@(\\w+\\.)+\\w{2,5})\\s*$").IsMatch(userName))
            {
                return _user.FindUserByEmail(userName, password);
            }
            else if (new Regex("^1\\d{10}$").IsMatch(userName))
            {
                return _user.FindUserByPhone(userName, password);
            }
            else
            {
                return null;
            }

        }

        public UserBaseModel FindUser(int userId)
        {
            return _cache.GetOrCreate("user-" + userId.ToString(), (entry) =>
            {
                entry.AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(20);
                return _user.FindUserByUserId(userId);
            });
        }

        public List<UserModel> GetAll()
        {
            return _user.GetAll();
        }

        public ResponseModel MargeAccount(LoginViewModel model, int userId, UserLevel userLevel)
        {
            //只允许新注册的账号合并
            if (userLevel != UserLevel.RegUser)
            {
                var res = new ResponseModel(ErrReason.OnlyAllowEmptyAccountToMerge);
                return res;
            }

            //查找目标账号
            var user = FindUser(model.Account, model.Password);
            if (user == null)
            {
                var res = new ResponseModel(ErrReason.UserNamePasswordsDoNotMatch);
                return res;
            }
            //存在目标账号
            else
            {
                //查看目标账号是否就是现在的账号
                if(user.UserId != userId)
                {
                    //转移资料
                    var usernow = FindUser(userId);

                    //搬迁所有的OAuth
                    _user.MoveAuth(userId, user.UserId);

                    //删除现有账号
                    _user.DeleteUser(userId);

                    //清空临时缓存
                    _cache.Remove("user-" + userId);
                }
                var res = new ResponseModel(ErrReason.Ok);
                res.result = new { token = getToken(user) };
                _cache.Set("user-" + user.UserId, FindUser(user.UserId), TimeSpan.FromMinutes(20));
                return res;
            }
        }

        public ResponseModel Login(LoginViewModel model, HttpContext context)
        {
            var user = FindUser(model.Account, model.Password);
            if (user == null)
            {
                var res = new ResponseModel(ErrReason.UserNamePasswordsDoNotMatch);
                return res;
            }
            else
            {
                var res = new ResponseModel(ErrReason.Ok);
                res.result = new { token = getToken(user) };
                _cache.Set("user-" + user.UserId, FindUser(user.UserId), TimeSpan.FromMinutes(20));
                return res;
            }

        }

        public string getToken(UserBaseModel user)
        {
            var claim = new Claim[]{
                    new Claim("UserId",user.UserId.ToString()),
                    new Claim("UserLevel", user.UserLevel.ToString()),
                };

            //对称秘钥
            var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_jwtSettings.SecretKey));
            //签名证书(秘钥，加密算法)
            var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
            //生成token  [注意]需要nuget添加Microsoft.AspNetCore.Authentication.JwtBearer包，并引用System.IdentityModel.Tokens.Jwt命名空间
            var token = new JwtSecurityToken(
                _jwtSettings.Issuer,
                _jwtSettings.Audience,
                claim,
                DateTime.Now,
                DateTime.Now.AddMinutes(30),
                creds);
            return new JwtSecurityTokenHandler().WriteToken(token);
        }

        public void SetUserLevel(UserBaseModel userModel)
        {
            _user.SetUserLevel(userModel);
        }

        public RowsModel getUsersInfo(string filterstring, string multiSort, int skip = 0, int take = 15)
        {
            JObject filter = (JObject)JsonConvert.DeserializeObject(filterstring);
            JArray orderobj = (JArray)JsonConvert.DeserializeObject(multiSort);
            string orderstr = String.Empty;
            foreach (var sort in orderobj)
            {
                if (orderstr != String.Empty) orderstr += ",";
                orderstr += sort["sortName"].ToString() + " " + (String.Equals(sort["sortOrder"].ToString(), "desc", StringComparison.CurrentCultureIgnoreCase) ? "Descending" : "Asc");
            }
            skip = Math.Max(0, skip);
            take = Math.Max(1, take);
            return _user.getUsersInfo(filter, orderstr, skip, take);
        }

        public void ResetPassword(int userId)
        {
            _user.ResetPassword(userId);
        }

        public List<MenuModel> GetMenus(UserLevel userLevel)
        {
            var menus = new List<MenuModel>();
            if (userLevel >= UserLevel.RegUser)
            {
                menus.Add(new MenuModel
                {
                    Title = "User Center",
                    Link = "#",
                    Icon = "fa fa-home",
                    ChildMenu = new List<MenuModel>
                        {
                            new MenuModel{Title = "Home",Link = "ajax/home.html"},
                            new MenuModel{Title = "Profile",Link = "ajax/userinfo.html"},
                            new MenuModel{Title = "Password",Link = "ajax/editpassword.html"},
                        }
                });
            }
            if (userLevel >= UserLevel.AuthUser)
            {
                menus.Add(new MenuModel
                {
                    Title = "Evaluation Center",
                    Link = "#",
                    Icon = "fa fa-star-half-full",
                    ChildMenu = new List<MenuModel>
                        {
                            new MenuModel{Title = "Roles Requirements",Link = "ajax/requirements.html"},
                            new MenuModel{Title = "Self Evaluate",Link = "ajax/selfevaluation.html"},
                            new MenuModel{Title = "Evaluate Others",Link = "ajax/evaluationothers.html"},
                            new MenuModel{Title = "Others Evaluation",Link = "ajax/othersevaluation.html"},
                        }
                });
            }
            if (userLevel >= UserLevel.Admin)
            {
                menus.Add(new MenuModel
                {
                    Title = "Role Management",
                    Link = "#",
                    Icon = "fa fa-user-md",
                    ChildMenu = new List<MenuModel>
                        {
                            new MenuModel{Title = "Create Role",Link = "ajax/newrole.html"},
                            new MenuModel{Title = "Role Setting",Link = "ajax/editrole.html"},
                        }
                });
                menus.Add(new MenuModel
                {
                    Title = "Skills Management",
                    Link = "#",
                    Icon = "fa fa-legal",
                    ChildMenu = new List<MenuModel>
                        {
                            new MenuModel{Title = "Skills Setting",Link = "ajax/editskill.html"},
                            new MenuModel{Title = "Levels Setting",Link = "ajax/editlevel.html"},
                        }
                });
            }
            if (userLevel == UserLevel.SuperAdmin)
            {
                menus.Add(new MenuModel
                {
                    Title = "Users Management",
                    Link = "#",
                    Icon = "fa fa-user-md",
                    ChildMenu = new List<MenuModel>
                        {
                            new MenuModel{Title = "Administrators Setting",Link = "ajax/levelsetting.html"},
                            new MenuModel{Title = "Job Transfer",Link = "ajax/changerole.html"},
                        }
                });
            }
            menus.Add(new MenuModel { Title = "About", Link = "ajax/about.html", Icon = "fa fa-info" });
            return menus;
        }

        public OAuthModel FindOAuth(OAuthModel oAuthModel,int userId = 0,UserLevel userLevel = UserLevel.NoLogin)
        {
            OAuthModel oAuth = _user.FindOAuth(oAuthModel);
            //openid不存在（新用户）
            if (oAuth.UserId==0)
            {
                //未登录的新用户（新增一个用户）
                if (userId == 0)
                {
                    userId = _user.AddUser(new UserModel
                    {
                        CreateBy = 0,
                        CreateOn = DateTime.Now,
                        Guid = Guid.NewGuid(),
                        IsDelete = false,
                        RoleChildId = null,
                        UserLevel = UserLevel.RegUser,
                        UserName = "",
                        UserNick = oAuthModel.NickName,
                        UserPassword = "",
                        UserPhone = ""
                    });
                }
                oAuthModel.UserId = userId;
                //向oauth表添加一个行
                _user.AddOAuth(oAuthModel);
                oAuth = oAuthModel;
                if (userLevel == UserLevel.NoLogin)
                {
                    userLevel = UserLevel.RegUser;
                }
                oAuth.UserLevel = userLevel;
            }

            return oAuth;
            
        }
    }
}
